﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace BaserControlLibrary.WinForm
{
    public partial class ComboBoxMulti : UserControl
    {


        /// <summary>
        /// list 对象类型转为泛型List
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tModel"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        public static T ListObjuConversionListT<T>(T tModel, object model)
        {
            var modelType = model.GetType();
            var enumType = modelType.GetInterface("IEnumerable", false);
            if (modelType.IsGenericType && enumType != null)
            {
                if (tModel == null || tModel.Equals(DBNull.Value)) { return default(T); }
                Type convType = tModel.GetType();

                tModel = (T)Activator.CreateInstance(convType);
                var addMethod = convType.GetMethod("Add");
                var listObj = model as IEnumerable<object>;
                foreach (var obj in listObj)
                {
                    addMethod.Invoke(tModel, new object[] { obj });
                }
            }
            return tModel;
        }

        /// <summary>
        /// list 对象类型转为泛型List
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tModel"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        public static T GetObjectDefault<T>(T tModel)
        {
            if (tModel == null || tModel.Equals(DBNull.Value)) { return default(T); }
            Type convType = tModel.GetType();
            tModel = (T)Activator.CreateInstance(convType);
            return tModel;
        }

        int _comboxHeight = 0;

        private List<object> _privateSelectValue;
        private List<object> _privateSelectDisplay;
        List<object> _PrivateSelectValue 
        { 
            get => _privateSelectValue; 
            set 
            { 
                _privateSelectValue = value;
            } 
        }
        List<object> _PrivateSelectDisplay 
        { 
            get => _privateSelectDisplay; 
            set 
            { 
                _privateSelectDisplay = value;
                tbSelectedValue.Text = string.Join(",", _PrivateSelectDisplay.ToArray());
            } 
        }
        public ComboBoxMulti()
        {
            InitializeComponent();
            _comboxHeight = this.Size.Height;
            checkListBox.Items.Clear();
            _PrivateSelectValue = new List<object>();
            _PrivateSelectDisplay = new List<object>();
            this.Size = panel1.Size;

            panel3.Visible = false;
            ValueEventHandler += ComboBoxMulti_ValueEventHandler;
            checkListBox.ItemCheck += CheckListBox_ItemCheck;
        }

        /// <summary>
        /// 设置数据源
        /// </summary>
        public object DataSource
        {
            set
            {
                if (value == null)
                {
                    InitDataSourceObject();
                }
                checkListBox.ValueMember = ValueMember;
                checkListBox.DisplayMember = DisplayMember;
                this.checkListBox.DataSource = value;
                SetSelectValueObject();
                checkListBox.Update();
                checkListBox.Invalidate();
            }
            get
            {
                return checkListBox.DataSource;
            }
        }


        public delegate void MultiSelectedValueChangedDelegate(object sender, EventArgs e);
        [Browsable(true)]
        public event MultiSelectedValueChangedDelegate MulitSelectedValueChanged;
        /// <summary>
        /// 选中值改变了
        /// </summary>
        /// <param name="value"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void ComboBoxMulti_ValueEventHandler(object value)
        {
            if (value == null||string.IsNullOrWhiteSpace(ValueMember)) { return; }
            var modelType = value.GetType();
            var enumType = modelType.GetInterface("IEnumerable", false);
            if (modelType.IsGenericType && enumType != null)
            {
                var listObj = value as IEnumerable;
                if (listObj == null) { return; }
                foreach (var item in listObj)
                {
                    for (int i = 0; i < checkListBox.Items.Count; i++)
                    {
                        Type clbDataSourceType = checkListBox.Items[i].GetType();
                        var valueObj = clbDataSourceType.GetProperty(ValueMember).GetValue(checkListBox.Items[i], null);
                        if (valueObj.Equals(item))
                        {
                            checkListBox.SetItemChecked(i, true);
                            break;
                        }
                    }

                }
            }
        }

        private delegate void ValueChangedDelegate(object value);

        private event ValueChangedDelegate ValueEventHandler;

        private object selectedValue;
        private object selectedDisplay;
        public object SelectedValue
        {
            get
            {
                
                return selectedValue;
            }
            set
            {
                selectedValue = value;
                if (value != null) 
                 {
                    if (ValueEventHandler != null)
                    {
                        ValueEventHandler(selectedValue);
                    }
                    if (MulitSelectedValueChanged != null)
                    {
                        MulitSelectedValueChanged(this, new EventArgs());
                    }
                }
            }
        }
        public object SelectedDisplay 
        { 
            get => selectedDisplay; 
            set 
            { 
                selectedDisplay = value;
                
            } 
        }

        /// <summary>
        /// 获取选择项文本
        /// </summary>
        public string CheckedText
        {
            get
            {
                return tbSelectedValue.Text;
            }
            set
            {
                tbSelectedValue.Text = value;
            }
        }

        /// <summary>
        /// 初始化值
        /// </summary>
        private void InitDataSourceObject()
        {
            ValueEventHandler -= ComboBoxMulti_ValueEventHandler;
            _PrivateSelectValue = new List<object>();
            _PrivateSelectDisplay = new List<object>();
            SelectedValue = GetObjectDefault(SelectedValue);
            SelectedDisplay = GetObjectDefault(SelectedDisplay);
            ValueEventHandler += ComboBoxMulti_ValueEventHandler;
        }

        /// <summary>
        /// 设置选中值
        /// </summary>
        private void SetSelectValueObject()
        {
            ValueEventHandler -= ComboBoxMulti_ValueEventHandler;
            if (SelectedValue == null||SelectedValue.Equals(DBNull.Value) )
            {
                return;
            }
           
            SelectedValue = ListObjuConversionListT(SelectedValue, _PrivateSelectValue);
            SelectedDisplay = _PrivateSelectDisplay;
            ValueEventHandler += ComboBoxMulti_ValueEventHandler;
        }
        private string valueMember;
        /// <summary>
        /// 设置值
        /// </summary>
        public string ValueMember
        {
            get 
            {
                if (string.IsNullOrWhiteSpace(checkListBox.ValueMember)) 
                {
                    checkListBox.ValueMember = valueMember;
                }
                return checkListBox.ValueMember;
            }
            set
            {
                valueMember = value;
                checkListBox.ValueMember = valueMember;
            }
        }
        private string displayMember;
        /// <summary>
        /// 设置显示名称
        /// </summary>
        public string DisplayMember
        {
            get
            {
                if (string.IsNullOrWhiteSpace(checkListBox.DisplayMember))
                {
                    checkListBox.DisplayMember = displayMember;
                }
                return checkListBox.DisplayMember;
            }
            set
            {
                displayMember = value;
                checkListBox.DisplayMember = displayMember;
            }
        }
        /// <summary>
        /// 添加项
        /// </summary>
        public int AddItems(object value)
        {
            checkListBox.Items.Add(value);
            return checkListBox.Items.Count;
        }
        /// <summary>
        /// 选项集合
        /// </summary>
        public CheckedListBox.ObjectCollection Items
        {
            get
            {
                return checkListBox.Items;
            }
        }
        /// <summary>
        /// 获取选中项的文本
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public string GetItemText(object item)
        {
            return checkListBox.GetItemText(item);
        }



        /// <summary>
        /// 弹出下拉框或收起下拉框
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Btn_SelectBox_Click(object sender, EventArgs e)
        {
            if (panel3.Visible)
            {
                panel3.Hide();
                this.Size = panel1.Size;
                checkListBox.LostFocus -= CheckListBox_LostFocus;
                this.SendToBack();
                SetSelectValueObject();
               
            }
            else
            {
                this.Size = new Size(panel1.Size.Width, _comboxHeight);
                panel3.Visible = true;
                checkListBox.LostFocus += CheckListBox_LostFocus;
                checkListBox.Focus();
                this.BringToFront();
            }

        }
        private void CheckListBox_LostFocus(object sender, EventArgs e)
        {
            if (panel3.Visible)
            {
                //如果鼠标位置在下拉框按钮的以外地方，则隐藏下拉框
                if (!this.RectangleToScreen(this.Btn_SelectBox.ClientRectangle).Contains(Cursor.Position))
                {
                    Btn_SelectBox_Click(null, null);
                }
            }

        }
        /// <summary>
        /// 选中按钮事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CheckListBox_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            var dataSourceModel = this.checkListBox.Items[e.Index];

            object displayObj = null;
            object valueObj = null;

            if (dataSourceModel is DataRowView)
            {
                DataRowView drv = (DataRowView)dataSourceModel;
                displayObj = drv[DisplayMember];
                valueObj = drv[ValueMember];
            }
            else
            {
                Type clbDataSourceType = dataSourceModel.GetType();
                displayObj = clbDataSourceType.GetProperty(DisplayMember).GetValue(dataSourceModel, null);
                valueObj = clbDataSourceType.GetProperty(ValueMember).GetValue(dataSourceModel, null);
            }

            if (e.NewValue == CheckState.Checked)
            {
                _PrivateSelectDisplay.Add(displayObj);
                _PrivateSelectValue.Add(valueObj);
            }
            else
            {
                _PrivateSelectDisplay.Remove(displayObj);
                _PrivateSelectValue.Remove(valueObj);
            }
            _PrivateSelectValue = _PrivateSelectValue.Distinct().ToList();
            _PrivateSelectDisplay = _PrivateSelectDisplay.Distinct().ToList();
        }



        
        

        /// <summary>
        /// 选中所有
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Lab_SelectAll_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < checkListBox.Items.Count; i++)
            {
                checkListBox.SetItemChecked(i, true);
            }
        }
        /// <summary>
        /// 取消选中所有
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Lab_UnselectAll_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < checkListBox.Items.Count; i++)
            {
                checkListBox.SetItemChecked(i, false);
            }
        }
    }
}
